package com.wordplat.quickstart.xutils.http.request;

import com.wordplat.quickstart.xutils.common.util.LogUtil;
import com.wordplat.quickstart.xutils.http.ProgressHandler;
import com.wordplat.quickstart.xutils.http.RequestParams;
import com.wordplat.quickstart.xutils.http.app.RequestInterceptListener;
import com.wordplat.quickstart.xutils.http.app.ResponseParser;
import com.wordplat.quickstart.xutils.http.loader.Loader;
import com.wordplat.quickstart.xutils.http.loader.LoaderFactory;
import com.wordplat.quickstart.xutils.x;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * Created by wyouflf on 15/7/23.
 * Uri请求发送和数据接收
 *
 * @since 2021-05-09
 */
public abstract class UriRequest implements Closeable {
    protected final String queryUrl;
    protected final RequestParams params;
    protected final Loader<?> loader;

    protected ProgressHandler progressHandler = null;
    protected ResponseParser responseParser = null;
    protected RequestInterceptListener requestInterceptListener = null;

    /**
     * UriRequest
     *
     * @param params
     * @param loadType
     * @throws Throwable
     */
    public UriRequest(RequestParams params, Type loadType) throws Throwable {
        this.params = params;
        this.queryUrl = buildQueryUrl(params);
        this.loader = LoaderFactory.getLoader(loadType);
        this.loader.setParams(params);
    }

    /**
     * // build query
     *
     * @param params
     * @return String
     * @throws IOException
     */
    protected String buildQueryUrl(RequestParams params) throws IOException {
        return params.getUri();
    }

    /**
     * setProgressHandler
     *
     * @param progressHandler
     */
    public void setProgressHandler(ProgressHandler progressHandler) {
        this.progressHandler = progressHandler;
        this.loader.setProgressHandler(progressHandler);
    }

    public void setResponseParser(ResponseParser responseParser) {
        this.responseParser = responseParser;
    }

    public void setRequestInterceptListener(RequestInterceptListener requestInterceptListener) {
        this.requestInterceptListener = requestInterceptListener;
    }

    public RequestParams getParams() {
        return params;
    }

    /**
     * getRequestUri
     *
     * @return getRequestUri
     */
    public String getRequestUri() {
        return queryUrl;
    }

    /**
     * sendRequest
     *
     * @throws Throwable
     */
    public abstract void sendRequest() throws Throwable;

    /**
     * isLoading
     *
     * @return boolean
     */
    public abstract boolean isLoading();

    /**
     * getCacheKey
     *
     * @return String
     */
    public abstract String getCacheKey();

    /**
     * loadResult
     *
     * @return loadResult
     * @throws Throwable
     */
    public Object loadResult() throws Throwable {
        return this.loader.load(this);
    }

    /**
     * loadResultFromCache
     *
     * @return Object
     * @throws Throwable
     */
    public abstract Object loadResultFromCache() throws Throwable;

    /**
     * clearCacheHeader
     */
    public abstract void clearCacheHeader();

    /**
     * save2Cache
     */
    public void save2Cache() {
        x.task().run(new Runnable() {
            @Override
            public void run() {
                try {
                    loader.save2Cache(UriRequest.this);
                } catch (Throwable ex) {
                    LogUtil.e(ex.getMessage(), ex);
                }
            }
        });
    }

    /**
     * getInputStream
     *
     * @return InputStream
     * @throws IOException
     */
    public abstract InputStream getInputStream() throws IOException;

    @Override
    public abstract void close() throws IOException;

    /**
     * getContentLength
     *
     * @return long
     */
    public abstract long getContentLength();

    /**
     * getResponseCode
     *
     * @return int
     * @throws IOException
     */
    public abstract int getResponseCode() throws IOException;

    /**
     * getResponseMessage
     *
     * @return String
     * @throws IOException
     */
    public abstract String getResponseMessage() throws IOException;

    /**
     * getExpiration
     *
     * @return long
     */
    public abstract long getExpiration();

    /**
     * getLastModified
     *
     * @return long
     */
    public abstract long getLastModified();

    /**
     * getETag
     *
     * @return String
     */
    public abstract String getETag();

    /**
     * getResponseHeader
     *
     * @param name
     * @return String
     */
    public abstract String getResponseHeader(String name);

    /**
     * getResponseHeaders
     *
     * @return Map
     */
    public abstract Map<String, List<String>> getResponseHeaders();

    /**
     * getHeaderFieldDate
     *
     * @param name
     * @param defaultValue
     * @return long
     */
    public abstract long getHeaderFieldDate(String name, long defaultValue);

    @Override
    public String toString() {
        return getRequestUri();
    }
}
